package com.jie.exception;


import com.jie.response.RespBean;
import com.jie.response.ResponseCode;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.log4j.Log4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * 全局异常处理器
 */
@RestControllerAdvice
public class WebExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(WebExceptionHandler.class);
    /**
     * 处理服务器内异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public RespBean systemExceptionHandler(Exception e) {
        logger.error("处理服务器内异常{}",e.getMessage());
        return RespBean.error(ResponseCode.ERROR_SYSTEM.getCode(), e.getMessage());
    }

    /**
     *  处理请求参数格式错误
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public RespBean methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        ObjectError objectError = e.getBindingResult().getAllErrors().stream().findFirst().get();
        logger.error("处理请求参数格式错误{}",objectError.getDefaultMessage());
        return RespBean.error(ResponseCode.ERROR_PARAM.getCode(), objectError.getDefaultMessage());
    }

    /**
     *约束声明异常处理程序
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public RespBean constraintDeclarationExceptionHandler(ConstraintViolationException e) {
        ConstraintViolation<?> constraintViolation = e.getConstraintViolations().stream().findFirst().get();
        logger.error("处理约束声明异常处理程序错误{}",constraintViolation.getMessage());
        return RespBean.error(ResponseCode.ERROR_PARAM.getCode(), constraintViolation.getMessage());
    }

    /**
     *缺少ServletRequest参数例外处理程序
     * @param e
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public RespBean missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException e) {
        logger.error("缺少ServletRequest参数例外处理程序{}",e.getMessage());

        return RespBean.error(ResponseCode.ERROR_PARAM.getCode(),e.getMessage());
    }

    /**
     * 非法状态异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = IllegalStateException.class)
    public RespBean illegalStateExceptionHandler(IllegalStateException e) {
        logger.error("非法状态异常:{}",e.getMessage());
        return RespBean.error(ResponseCode.ERROR_PARAM.getCode(),e.getMessage());
    }

    /**
     *  处理所有接口数据验证不通过抛出的异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    public RespBean bindExceptionHandler(BindException e) {
        FieldError fieldError = e.getBindingResult().getFieldErrors().stream().findFirst().get();
        logger.error("处理所有接口数据验证不通过抛出的异常:{}",fieldError.getDefaultMessage());
        return RespBean.error(ResponseCode.ERROR_PARAM.getCode(), e.getMessage());
    }


    /**
     * 运行时异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = RuntimeException.class)
    public RespBean runtimeExceptionHandler(RuntimeException e) {
        logger.error("处理所有接口数据验证不通过抛出的异常:{}",e.getMessage());
        return RespBean.error(ResponseCode.ERROR.getCode(), e.getMessage());
    }
    /**
     * 登录异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = BizException.class)
    public RespBean bizExceptionHandler(BizException e) {
        logger.error("出现自定义异常:{}",e.getMessage());
        return RespBean.error(ResponseCode.ERROR.getCode(), e.getMessage());
    }
    @ExceptionHandler(value = ExpiredJwtException.class)
    public RespBean  bizExceptionHandler(ExpiredJwtException e) {
        logger.error("jwt时间过期:{}",e.getMessage());
        return  RespBean.error(ResponseCode.TOKEN_EXPIRE.getCode(), e.getMessage());
    }

    /**
     * 处理Assert异常
     */
    @ExceptionHandler(value = IllegalArgumentException.class)
    public RespBean<?> handleIllegalArgumentException(IllegalArgumentException e) {
        return RespBean.error(e.getMessage());
    }


}
